﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.Drawing.Text;

namespace Walson.Form.FlightDevice
{
    /// <summary>
    /// 主飞行数据显示器
    /// </summary>
    public partial class PrimaryFlightDisplay : Control
    {
        #region 属性

        private float _Bank;
        /// <summary>
        /// 侧倾角度
        /// </summary>
        public double Bank
        {
            get
            {
                return _Bank;
            }
            set
            {
                while (value < 0)
                    value += 360;
                _Bank = (float)value % 360;
                this.Invalidate();
            }
        }

        private float _Pitch;
        /// <summary>
        /// 俯仰角度
        /// </summary>
        public double Pitch
        {
            get
            {
                return _Pitch;
            }
            set
            {
                while (value < -360)
                    value += 360;
                while (value > 360)
                    value -= 360;
                _Pitch = (float)value % 360;
                this.Invalidate();
            }
        }

        private float _Altitude;
        /// <summary>
        /// 海拔高度
        /// </summary>
        public double Altitude
        {
            get
            {
                return _Altitude;
            }
            set
            {
                _Altitude = (float)value;
                this.Invalidate();
            }
        }

        private float _AirSpeed;
        /// <summary>
        /// 空速
        /// </summary>
        public double AirSpeed
        {
            get
            {
                return _AirSpeed;
            }
            set
            {
                _AirSpeed = (float)value;
                this.Invalidate();
            }
        }

        private float _BankLimit;
        /// <summary>
        /// 侧倾角限制
        /// </summary>
        public double BankLimit
        {
            get
            {
                return _BankLimit;
            }
            set
            {
                while (value > 360)
                    value -= 360;
                while (value < 0)
                    value += 360;

                if (BankLimit != value)
                {
                    _BankLimit = (float)value % 360;
                    this.Invalidate();
                }

            }
        }

        private bool _OverSpeed;
        /// <summary>
        /// 是否超速
        /// </summary>
        public bool OverSpeed
        {
            get
            {
                return _OverSpeed;
            }
            set
            {
                if (value != _OverSpeed)
                {
                    _OverSpeed = value;
                    this.Invalidate();
                }
            }
        }

        private bool _Stall;
        /// <summary>
        /// 是否失速
        /// </summary>
        public bool Stall
        {
            get
            {
                return _Stall;
            }
            set
            {
                if (value != _Stall)
                {
                    _Stall = value;
                    this.Invalidate();
                }
            }
        }

        private string _MJpegUrl;
        /// <summary>
        /// MJpeg地址
        /// </summary>
        public string MJpegUrl
        {
            get
            {
                return _MJpegUrl;
            }
            set
            {
                _MJpegUrl = value;
                this.Invalidate();
            }
        }

        private bool _ShowMJpegStream;
        /// <summary>
        /// 是否显示 MJpeg 流
        /// </summary>
        public bool ShowMJpegStream
        {
            get
            {
                return _ShowMJpegStream;
            }
            set
            {
                _ShowMJpegStream = value;
                this.Invalidate();
            }
        }

        private float _HeightFromGround;
        /// <summary>
        /// 距离地面的高度
        /// </summary>
        public double HeightFromGround
        {
            get
            {
                return _HeightFromGround;
            }
            set
            {
                _HeightFromGround = (float)value;
                this.Invalidate();
            }
        }

        private int _DangerHeight = 300;
        /// <summary>
        /// 危险高度
        /// </summary>
        public int DangerHeight
        {
            get
            {
                return _DangerHeight;
            }
            set
            {
                _DangerHeight = value;
                this.Invalidate();
            }
        }

        private int _SleepTime;
        private int _FrameRate;
        /// <summary>
        /// MJpeg 流的帧率
        /// </summary>
        public int FrameRate
        {
            get
            {
                return _FrameRate;
            }
            set
            {
                _FrameRate = value;
                _SleepTime = 1000 / _FrameRate;
            }
        }

        private float _DestinationAltitude;
        /// <summary>
        /// 预设的海拔高度
        /// </summary>
        public float DestinationAltitude
        {
            get
            {
                return _DestinationAltitude;
            }
            set
            {
                _DestinationAltitude = value;
                this.Invalidate();
            }
        }

        private float _DestinationAirSpeed;
        /// <summary>
        /// 预设的空速
        /// </summary>
        public float DestinationAirSpeed
        {
            get
            {
                return _DestinationAirSpeed;
            }
            set
            {
                _DestinationAirSpeed = value;
                this.Invalidate();
            }
        }

        private float _GroundAltitude;
        /// <summary>
        /// 地面海拔高度
        /// </summary>
        public float GroundAltitude
        {
            get
            {
                return _GroundAltitude;
            }
            set
            {
                _GroundAltitude = value;
                this.Invalidate();
            }
        }

        private float _Heading;
        /// <summary>
        /// 航向
        /// </summary>
        public float Heading
        {
            get
            {
                return _Heading;
            }
            set
            {
                if (value != _Heading)
                {
                    while (value < 0)
                        value += 360;
                    while (value > 360)
                        value -= 360;
                    _Heading = value;
                    this.Invalidate();
                }
            }
        }

        private float _VerticalSpeed;
        /// <summary>
        /// 垂直速度
        /// </summary>
        public float VerticalSpeed
        {
            get
            {
                return _VerticalSpeed;
            }
            set
            {
                if (_VerticalSpeed != value)
                {
                    _VerticalSpeed = value;
                    this.Invalidate();
                }
            }
        }

        #endregion

        #region 变量

        private Bitmap _MJpegStream;
        private Pen _RedPen;
        private Pen _PinkPen;

        private int _Max = 360;
        private int _Min = 0;
        private const float _gap = 60;

        #endregion

        private Pen _WhitePen;

        /// <summary>
        /// 主飞行数据显示器
        /// </summary>
        public PrimaryFlightDisplay()
        {
            InitializeComponent();
            this.DoubleBuffered = true;


            _WhitePen = new Pen(Brushes.White, 2);
            _RedPen = new Pen(Brushes.Red, 4);
            _PinkPen = new Pen(Color.FromArgb(255, 125, 255), 2);

            _BankLimit = 45;
            _FrameRate = 15;
            _MJpegUrl = string.Empty;
            _ShowMJpegStream = false;

            this.BackColor = Color.FromArgb(16, 16, 49);

            this.SizeChanged += delegate
            {
                this.Invalidate();
            };
        }

        private Bitmap DrawPitchAndBank(int width,int height)
        {
            Bitmap bmp = new Bitmap(width, height);
            {
                using (Graphics g = Graphics.FromImage(bmp))
                {
                    g.SmoothingMode = SmoothingMode.AntiAlias;
                    g.TextRenderingHint = TextRenderingHint.AntiAlias;

                    g.Clear(Color.Transparent);   

                    PointF[] polygon;

                    if (_ShowMJpegStream == true)
                    {
                        if (_MJpegStream != null)
                            g.DrawImage(_MJpegStream, 0, 0);
                    }

                    // 设置平移
                    g.TranslateTransform(width / 2f, height / 2f);

                    // 设置旋转
                    g.RotateTransform(_Bank);
                    g.TranslateTransform(0, _Pitch * 6f);

                    if (_ShowMJpegStream == false)
                    {
                        g.Clear(Color.FromArgb(99, 57, 24));
                        

                        // 绘制天和地
                        polygon = new PointF[4];
                        polygon[0] = new PointF(-Width * 5f, 0f);
                        polygon[1] = new PointF(Width * 5f, 0f);
                        polygon[2] = new PointF(Width * 5f, -Height * 5f);
                        polygon[3] = new PointF(-Width * 5f, -Height * 5f);
                        g.FillPolygon(new SolidBrush(Color.FromArgb(41, 156, 239)), polygon);
                        // 天地分界线
                        g.DrawLine(_WhitePen, -Width * 5f, 0, Width * 5f, 0);
                    }

                    // 绘制俯仰角度刻度线
                    for (int i = 0; i <= 36; i++)
                    {

                        if (i % 4 == 0)
                        {
                            if ((i * 15f > -height / 2f + 50 - _Pitch * 6))
                            {
                                g.DrawLine(_WhitePen, -40, i * 15f, 40, i * 15f);
                                g.DrawString((i / 4 * 10).ToString(), new Font("Times NewRoman", 10f, FontStyle.Bold), Brushes.White, 46, i * 15f - 7);
                                g.DrawString((i / 4 * 10).ToString(), new Font("Times NewRoman", 10f, FontStyle.Bold), Brushes.White, -71, i * 15f - 7);
                            }
                            if (!(-i * 15f < -height / 2f + 50 - _Pitch * 6))
                            {
                                g.DrawLine(_WhitePen, -40, -i * 15f, 40, -i * 15f);
                                g.DrawString((i / 4 * 10).ToString(), new Font("Times NewRoman", 10f, FontStyle.Bold), Brushes.White, 46, -i * 15f - 7);
                                g.DrawString((i / 4 * 10).ToString(), new Font("Times NewRoman", 10f, FontStyle.Bold), Brushes.White, -71, -i * 15f - 7);
                            }
                        }
                        else if (i % 2 == 0)
                        {
                            if ((i * 15f > -height / 2f + 50 - _Pitch * 6))
                                g.DrawLine(_WhitePen, -20, i * 15f, 20, i * 15f);
                            if (!(-i * 15f < -height / 2f + 50 - _Pitch * 6))
                                g.DrawLine(_WhitePen, -20, -i * 15f, 20, -i * 15f);
                        }
                        else
                        {
                            if ((i * 15f > -height / 2f + 50 - _Pitch * 6))
                                g.DrawLine(_WhitePen, -10, i * 15f, 10, i * 15f);
                            if (!(-i * 15f < -height / 2f + 50 - _Pitch * 6))
                                g.DrawLine(_WhitePen, -10, -i * 15f, 10, -i * 15f);
                        }
                    }

                    // 绘制三角形
                    g.ResetTransform();
                    g.TranslateTransform(width / 2f, height / 2f);
                    g.RotateTransform(_Bank);
                    PointF[] triangle = new PointF[4];
                    triangle[0] = new PointF(0, 30 - height / 2);
                    triangle[1] = new PointF(-10, 45.77f - height / 2);
                    triangle[2] = new PointF(10, 45.77f - height / 2);
                    triangle[3] = new PointF(0, 30 - height / 2);
                    g.DrawLines(_WhitePen, triangle);
                    if (_Bank < _BankLimit || _Bank > 360 - _BankLimit)
                        g.FillPolygon(Brushes.Yellow, triangle);
                    else
                        g.FillPolygon(Brushes.Red, triangle);

                    // 恢复平移和旋转
                    g.ResetTransform();
                    //g.DrawString(_Pitch.ToString(), this.Font, Brushes.Black, 10, 10);
                    // 设置平移
                    g.TranslateTransform(width / 2f, height / 2f);
                    // 中间的小方块
                    g.DrawRectangle(_WhitePen, -4, 0, 8, 8);

                    // 绘制水平指示
                    PointF[] centerIndicator = new PointF[7];
                    centerIndicator[0] = new PointF(-25, 0);
                    centerIndicator[1] = new PointF(-90, 0);
                    centerIndicator[2] = new PointF(-90, 7);
                    centerIndicator[3] = new PointF(-32, 7);
                    centerIndicator[4] = new PointF(-32, 20);
                    centerIndicator[5] = new PointF(-25, 20);
                    centerIndicator[6] = new PointF(-25, 0);
                    g.FillPolygon(Brushes.Black, centerIndicator);
                    g.DrawLines(_WhitePen, centerIndicator);

                    centerIndicator[0] = new PointF(25, 0);
                    centerIndicator[1] = new PointF(90, 0);
                    centerIndicator[2] = new PointF(90, 7);
                    centerIndicator[3] = new PointF(32, 7);
                    centerIndicator[4] = new PointF(32, 20);
                    centerIndicator[5] = new PointF(25, 20);
                    centerIndicator[6] = new PointF(25, 0);
                    g.FillPolygon(Brushes.Black, centerIndicator);
                    g.DrawLines(_WhitePen, centerIndicator);



                    // 绘制顶上的量角器
                    double r1 = Math.Min(width, height) / 2, r2 = r1 - 20;
                    double x1, y1, x2, y2;
                    for (int i = -180; i <= 0; i += 10)
                    {
                        if (i % 30 == 0)
                        {
                            x1 = r1 * Math.Cos(Math.PI * i / 180.0);
                            y1 = r1 * Math.Sin(Math.PI * i / 180.0);
                            x2 = r2 * Math.Cos(Math.PI * i / 180.0);
                            y2 = r2 * Math.Sin(Math.PI * i / 180.0);
                        }
                        else
                        {
                            x1 = (r1 - 10) * Math.Cos(Math.PI * i / 180.0);
                            y1 = (r1 - 10) * Math.Sin(Math.PI * i / 180.0);
                            x2 = r2 * Math.Cos(Math.PI * i / 180.0);
                            y2 = r2 * Math.Sin(Math.PI * i / 180.0);
                        }
                        g.DrawLine(_WhitePen, (float)x1, (float)y1, (float)x2, (float)y2);
                    }

                    g.ResetTransform();
                    System.Drawing.Drawing2D.GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath();
                    if (_OverSpeed)
                    {
                        //                         path.AddString("超速", new FontFamily("宋体"),2 , 20, new Point(20, 20), StringFormat.GenericDefault);
                        //                         g.FillPath(Brushes.Red,path);
                        //                         g.DrawPath(Pens.White,path);
                        Point txtPoint = new Point(12, 12);
                        Font font = new Font("宋体", 12, FontStyle.Bold);
                        string str = "超速";
                        // txtPoint是绘制文字的定位点
                        txtPoint.Offset(-1, 0);  // 绘制左背景文字
                        g.DrawString(str, font, Brushes.White, txtPoint);
                        txtPoint.Offset(2, 0);  // 绘制右背景文字
                        g.DrawString(str, font, Brushes.White, txtPoint);
                        txtPoint.Offset(-1, -1);  // 绘制下背景文字
                        g.DrawString(str, font, Brushes.White, txtPoint);
                        txtPoint.Offset(0, 2);  // 绘制上背景文字
                        g.DrawString(str, font, Brushes.White, txtPoint);
                        txtPoint.Offset(0, -1);  // 定位点归位
                        g.DrawString(str, font, Brushes.Red, txtPoint);
                    }
                    if (_Stall)
                    {
                        Point txtPoint = new Point(12, 12);
                        Font font = new Font("宋体", 12, FontStyle.Bold);
                        string str = "失速";
                        // txtPoint是绘制文字的定位点
                        txtPoint.Offset(-1, 0);  // 绘制左背景文字
                        g.DrawString(str, font, Brushes.White, txtPoint);
                        txtPoint.Offset(2, 0);  // 绘制右背景文字
                        g.DrawString(str, font, Brushes.White, txtPoint);
                        txtPoint.Offset(-1, -1);  // 绘制下背景文字
                        g.DrawString(str, font, Brushes.White, txtPoint);
                        txtPoint.Offset(0, 2);  // 绘制上背景文字
                        g.DrawString(str, font, Brushes.White, txtPoint);
                        txtPoint.Offset(0, -1);  // 定位点归位
                        g.DrawString(str, font, Brushes.Red, txtPoint);
                    }
                    // 高度小于危险高度时开始提示
                    if (_HeightFromGround <= _DangerHeight)
                    {
                        string str = _HeightFromGround.ToString("f0")/* + " cm"*/;
                        Font font = new Font("Times NewRoman", 10f, FontStyle.Bold);
                        SizeF size = g.MeasureString(str, font);
                        Rectangle rect0;
                        if (size.Width < 40)
                            rect0 = new Rectangle((int)(width / 2 - 20), (int)(height - 25), 40, 20);
                        else
                            rect0 = new Rectangle((int)(width / 2 - size.Width / 2 - 5), (int)(height - 25), (int)(size.Width + 10), 20);
                        //Point strLocation = new Point((int)(width / 2 - size.Width / 2), (int)(height - 25 + size.Height / 2));
                        PointF strLocation = new PointF((width / 2 - size.Width / 2 + 1), (height - 13f - size.Height / 2));
                        g.FillRectangle(new SolidBrush(Color.FromArgb(16, 16, 49)), rect0);
                        g.DrawRectangle(Pens.White, rect0);
                        g.DrawString(str, font, Brushes.White, strLocation);
                    }

                    // 绘制圆角
                    Rectangle rect = new Rectangle(0, 0, width, height);
                    int radius = 50;
                    System.Drawing.Drawing2D.GraphicsPath roundRect = new System.Drawing.Drawing2D.GraphicsPath();
                    //顶端 
                    roundRect.AddLine(rect.Left + radius - 1, rect.Top - 1, rect.Right - radius, rect.Top - 1);
                    //右上角 
                    roundRect.AddArc(rect.Right - radius, rect.Top - 1, radius, radius, 270, 90);
                    //右边 
                    roundRect.AddLine(rect.Right, rect.Top + radius, rect.Right, rect.Bottom - radius);
                    //右下角
                    roundRect.AddArc(rect.Right - radius, rect.Bottom - radius, radius, radius, 0, 90);
                    //底边 
                    roundRect.AddLine(rect.Right - radius, rect.Bottom, rect.Left + radius, rect.Bottom);
                    //左下角 
                    roundRect.AddArc(rect.Left - 1, rect.Bottom - radius, radius, radius, 90, 90);
                    //左边 
                    roundRect.AddLine(rect.Left - 1, rect.Top + radius, rect.Left - 1, rect.Bottom - radius);
                    //左上角 
                    roundRect.AddArc(rect.Left - 1, rect.Top - 1, radius, radius, 180, 90);
                    // 外框
                    roundRect.AddRectangle(rect);
                    g.FillRegion(new SolidBrush(this.BackColor), new Region(roundRect));
                }
            }
            
            return bmp;
        }

        private Bitmap DrawAirSpeedAndAltitudeIndicator(int width, int height, bool IsLeftStyle)
        {
            Bitmap bmp = new Bitmap(width, height);
            {
                using (Graphics g = Graphics.FromImage(bmp))
                {
                    g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
                    g.TextRenderingHint = TextRenderingHint.AntiAlias;

                    PointF[] line = new PointF[2];
                    PointF[] polygon;
                    string str;
                    Font font = new Font("Times NewRoman", 12f);
                    float len, fontHeight;

                    g.Clear(Color.FromArgb(57, 49, 66));

                    if (IsLeftStyle)
                    {
                        g.TranslateTransform((float)width - 25, _AirSpeed * 2f + height / 2f);

                        polygon = new PointF[4];
                        polygon[0] = new PointF(0, -2000);
                        polygon[1] = new PointF(0, 500);
                        polygon[2] = new PointF(25, 500);
                        polygon[3] = new PointF(25, -2000);
                        g.FillPolygon(new SolidBrush(Color.FromArgb(16, 16, 49)), polygon);


                        for (int i = 0; i < _AirSpeed + 1000; i++)
                        {
                            line[0] = new PointF(0, -i * 20);
                            line[1] = new PointF(-10, -i * 20);

                            g.DrawLine(_WhitePen, line[0], line[1]);

                            if (i % 2 == 0)
                            {
                                str = (i * 10).ToString("D2");
                                font = new Font("Times NewRoman", 12f);
                                len = g.MeasureString(str, font).Width;
                                g.DrawString(str, font, Brushes.White, -len - 15, -i * 20f - 10);
                            }
                        }

                        for (int i = -1; i > -50; i--)
                        {
                            line[0] = new PointF(10, -i * 10);
                            line[1] = new PointF(0, -i * 10);

                            g.DrawLine(_RedPen, line[0], line[1]);
                        }

                        len = g.MeasureString("000", font).Width + 30;
                        fontHeight = (g.MeasureString("000", font).Height + 10) / 2f;
                        polygon = new PointF[8];
                        polygon[0] = new PointF(-15, 0 - _AirSpeed * 2f);
                        polygon[1] = new PointF(-20, 5 - _AirSpeed * 2f);
                        polygon[2] = new PointF(-20, fontHeight - _AirSpeed * 2f);
                        polygon[3] = new PointF(-len, fontHeight - _AirSpeed * 2f);
                        polygon[4] = new PointF(-len, -fontHeight - _AirSpeed * 2f);
                        polygon[5] = new PointF(-20, -fontHeight - _AirSpeed * 2f);
                        polygon[6] = new PointF(-20, -5 - _AirSpeed * 2f);
                        polygon[7] = new PointF(-15, 0 - _AirSpeed * 2f);
                        g.FillPolygon(new SolidBrush(Color.FromArgb(16, 16, 49)), polygon);
                        g.DrawLines(_WhitePen, polygon);
                        g.DrawString(((int)_AirSpeed).ToString("D3"), font, Brushes.White, -len + 5, -10 - _AirSpeed * 2f);

                        float basePointY = -_DestinationAirSpeed * 2f;

                        if (basePointY > -_AirSpeed * 2f + height / 2f)
                            basePointY = -_AirSpeed * 2f + height / 2f;
                        else if (basePointY < -_AirSpeed * 2f - height / 2f)
                            basePointY = -_AirSpeed * 2f - height / 2f;

                        polygon = new PointF[6];
                        polygon[0] = new PointF(-10, basePointY);
                        polygon[1] = new PointF(0, basePointY - 5);
                        polygon[2] = new PointF(18, basePointY - 5);
                        polygon[3] = new PointF(18, basePointY + 5);
                        polygon[4] = new PointF(0, basePointY + 5);
                        polygon[5] = new PointF(-10, basePointY);
                        g.FillPolygon(new SolidBrush(Color.FromArgb(16, 16, 49)), polygon);
                        g.DrawLines(_PinkPen, polygon);
                    }
                    else
                    {
                        g.TranslateTransform(0, (float)this._Altitude * 0.4f + height / 2f);

                        // 绘制近地警告标识
                        polygon = new PointF[4];
                        polygon[0] = new PointF(0, -_GroundAltitude * 0.4f);
                        polygon[1] = new PointF(50, -_GroundAltitude * 0.4f);
                        polygon[2] = new PointF(50, 20 - _GroundAltitude * 0.4f);
                        polygon[3] = new PointF(0, 20 - _GroundAltitude * 0.4f);
                        System.Drawing.Drawing2D.HatchBrush myHatchBrush = new System.Drawing.Drawing2D.HatchBrush(System.Drawing.Drawing2D.HatchStyle.LightDownwardDiagonal, Color.Gold, Color.Transparent);
                        g.FillPolygon(myHatchBrush, polygon, System.Drawing.Drawing2D.FillMode.Alternate);
                        g.DrawLines(Pens.Yellow, polygon);

                        // 绘制正向高度尺
                        for (int i = 0; i < _Altitude / 100 + 500; i++)
                        {
                            line[0] = new PointF(0, -i * 40);
                            line[1] = new PointF(10, -i * 40);

                            g.DrawLine(_WhitePen, line[0], line[1]);

                            if (i % 2 == 0)
                            {
                                str = (i * 100).ToString("D3");
                                g.DrawString(str, font, Brushes.White, 15, -i * 40f - 10);
                            }
                        }
                        // 绘制负向高度尺
                        for (int i = -1; i > -300; i--)
                        {
                            line[0] = new PointF(0, -i * 40);
                            line[1] = new PointF(10, -i * 40);

                            g.DrawLine(_WhitePen, line[0], line[1]);

                            if (i % 2 == 0)
                            {
                                str = (i * 100).ToString("D3");
                                g.DrawString(str, font, Brushes.White, 15, -i * 40f - 10);
                            }
                        }

                        // 绘制设置高度
                        polygon = new PointF[8];
                        float basePointY;
                        basePointY = -DestinationAltitude * 0.4f;

                        if (basePointY > -_Altitude * 0.4f + height / 2f)
                            basePointY = -_Altitude * 0.4f + height / 2f;
                        else if (basePointY < -_Altitude * 0.4f - height / 2f)
                            basePointY = -_Altitude * 0.4f - height / 2f;

                        polygon[0] = new PointF(7, basePointY);
                        polygon[1] = new PointF(2, basePointY - 5);
                        polygon[2] = new PointF(2, basePointY - 25);
                        polygon[3] = new PointF(35, basePointY - 25);
                        polygon[4] = new PointF(35, basePointY + 25);
                        polygon[5] = new PointF(2, basePointY + 25);
                        polygon[6] = new PointF(2, basePointY + 5);
                        polygon[7] = new PointF(7, basePointY);
                        g.DrawLines(_PinkPen, polygon);

                        // 绘制高度读数
                        len = g.MeasureString("0000", font).Width + 32;
                        fontHeight = (g.MeasureString("0000", font).Height + 10) / 2f;
                        polygon[0] = new PointF(12, 0 - _Altitude * 0.4f);
                        polygon[1] = new PointF(20, 5 - _Altitude * 0.4f);
                        polygon[2] = new PointF(20, fontHeight - _Altitude * 0.4f);
                        polygon[3] = new PointF(len, fontHeight - _Altitude * 0.4f);
                        polygon[4] = new PointF(len, -fontHeight - _Altitude * 0.4f);
                        polygon[5] = new PointF(20, -fontHeight - _Altitude * 0.4f);
                        polygon[6] = new PointF(20, -5 - _Altitude * 0.4f);
                        polygon[7] = new PointF(12, 0 - _Altitude * 0.4f);
                        g.FillPolygon(new SolidBrush(Color.FromArgb(16, 16, 49)), polygon);
                        g.DrawLines(_WhitePen, polygon);
                        g.DrawString(((int)_Altitude).ToString("D4"), font, Brushes.White, 22, -10 - _Altitude * 0.4f);


                    }
                    g.ResetTransform();
                }

            }
            return bmp;
        }

        private Bitmap DrawRectangleCompass(int width,int height)
        {
            Bitmap bmp = new Bitmap(width, height);
            {
                using (Graphics g = Graphics.FromImage(bmp))
                {
                    Font font = new Font("Times NewRoman", 10f);

                    g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
                    g.TextRenderingHint = TextRenderingHint.AntiAlias;

                    g.Clear(Color.FromArgb(57, 49, 66));

                    PointF[] polygon = new PointF[3];
                    polygon[0] = new PointF(width / 2, 7);
                    polygon[1] = new PointF(width / 2 - 5, 2);
                    polygon[2] = new PointF(width / 2 + 5, 2);

                    g.FillPolygon(Brushes.White, polygon);

                    float offset = (float)(_Heading - (int)_Heading);
                    float start = width / 2 - offset * _gap;
                    PointF[] line = new PointF[2];
                    float x;
                    for (int i = 0; i < width / (_gap / 2); i++)
                    {
                        x = i * _gap / 2;
                        line[0] = new PointF(start + i * _gap / 2, 10);
                        line[1] = new PointF(start + i * _gap / 2, 17);
                        g.DrawLine(_WhitePen, line[0], line[1]);

                        line[0] = new PointF(start - i * _gap / 2, 10);
                        line[1] = new PointF(start - i * _gap / 2, 17);
                        g.DrawLine(_WhitePen, line[0], line[1]);

                        if (i % 2 == 0)
                        {
                            int h;
                            float len;

                            if (_Heading >= 0)
                                h = (int)Math.Floor(_Heading + i / 2);
                            else
                                h = (int)Math.Ceiling(_Heading + i / 2);


                            while (h < _Min)
                                h = _Max - (_Min - h);
                            while (h > _Max)
                                h = _Min + h - _Max;
                            if (h == _Max)
                                h = _Min;

                            len = g.MeasureString(h.ToString(), font).Width;
                            g.DrawString(h.ToString(), font, Brushes.White, start + i * _gap / 2 - len / 2, 19);

                            if (_Heading >= 0)
                                h = (int)Math.Floor(_Heading - i / 2);
                            else
                                h = (int)Math.Ceiling(_Heading - i / 2);

                            while (h < _Min)
                                h = _Max - (_Min - h);
                            while (h > _Max)
                                h = _Min + h - _Max;
                            if (h == _Max)
                                h = _Min;
                            len = g.MeasureString(h.ToString(), font).Width;
                            g.DrawString(h.ToString(), font, Brushes.White, start - i * _gap / 2 - len / 2, 19);
                        }
                    }

                    g.ResetTransform();
                }
            }
            return bmp;
        }

        private Bitmap DrawVerticalSpeedIndicator(int width, int height)
        {
            Bitmap bmp = new Bitmap(width, height);
            {
                using (Graphics g = Graphics.FromImage(bmp))
                {
                    g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
                    g.TextRenderingHint = TextRenderingHint.AntiAlias;

                    Font font = new Font("Times NewRoman", 9f);

                    g.Clear(Color.FromArgb(16, 16, 49));

                    PointF[] polygon = new PointF[7];
                    polygon[0] = new PointF(0, 0);
                    polygon[1] = new PointF(25, 0);
                    polygon[2] = new PointF(width, height / 2 - 20);
                    polygon[3] = new PointF(width, height / 2 + 20);
                    polygon[4] = new PointF(25, height);
                    polygon[5] = new PointF(0, height);
                    polygon[6] = new PointF(0, 0);
                    g.FillPolygon(new SolidBrush(Color.FromArgb(57, 49, 66)), polygon);

                    g.TranslateTransform(0, height / 2f);

                    PointF[] line = new PointF[2];
                    int gap = height / 10 - 2;
                    for (int i = 0; i < 6; i++)
                    {
                        line[0] = new PointF(15, i * gap);
                        line[1] = new PointF(20, i * gap);
                        g.DrawLine(_WhitePen, line[0], line[1]);

                        line[0] = new PointF(15, -i * gap);
                        line[1] = new PointF(20, -i * gap);
                        g.DrawLine(_WhitePen, line[0], line[1]);

                        g.DrawString(i.ToString(), font, Brushes.White, 2, i * gap - 9);
                        g.DrawString(i.ToString(), font, Brushes.White, 2, -i * gap - 9);
                    }

                    line[0] = new PointF(width, 0);
                    if (VerticalSpeed > 5)
                        line[1] = new PointF(25, -gap * 5);
                    else if (VerticalSpeed < -5)
                        line[1] = new PointF(25, -gap * -5);
                    else
                        line[1] = new PointF(25, -gap * _VerticalSpeed);
                    g.DrawLine(_WhitePen, line[0], line[1]);
                }
            }
            return bmp;
        }

        /// <summary>
        /// 绘图
        /// </summary>
        /// <param name="pe">参数</param>
        protected override void OnPaint(PaintEventArgs pe)
        {
            using (Bitmap bmp = new Bitmap(475, 327))
            {
                using (Graphics g = Graphics.FromImage(bmp))
                {
                    g.SmoothingMode = SmoothingMode.HighQuality;
                    g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;

                    g.Clear(this.BackColor);

                    Bitmap pab = DrawPitchAndBank(250, 242);
                    Bitmap asi = DrawAirSpeedAndAltitudeIndicator(92, 285, true);
                    Bitmap ati = DrawAirSpeedAndAltitudeIndicator(79, 285, false);
                    Bitmap compass = DrawRectangleCompass(250, 37);
                    Bitmap vsi = DrawVerticalSpeedIndicator(37, 182);

                    g.DrawImage(asi, 0, 29);
                    g.DrawImage(pab, 93, 29);
                    g.DrawImage(ati, 349, 29);
                    g.DrawImage(compass, 93, 277);
                    g.DrawImage(vsi, 433, 75);

                    Font font = new Font("Times NewRoman", 12, FontStyle.Bold);
                    g.DrawString(_DestinationAirSpeed.ToString("f0"), font, Brushes.Magenta, 10, 10);
                    g.DrawString(_DestinationAltitude.ToString("f0"), font, Brushes.Magenta, 349, 10);

                    if (_VerticalSpeed > 0)
                    {
                        g.DrawString(_VerticalSpeed.ToString("f0"), font, Brushes.White, 433, 55);
                    }
                    else if (_VerticalSpeed < 0)
                    {
                        g.DrawString(_VerticalSpeed.ToString("f0"), font, Brushes.White, 433, 260);
                    }

                    pab.Dispose();
                    pab = null;
                    asi.Dispose();
                    asi = null;
                    ati.Dispose();
                    ati = null;
                    compass.Dispose();
                    compass = null;
                    vsi.Dispose();
                    vsi = null;

                }
                pe.Graphics.DrawImage(bmp, new Rectangle(0, 0, this.Width, this.Height), new Rectangle(0, 0, bmp.Width, bmp.Height), GraphicsUnit.Pixel);
            }

            // 绘制圆角
            Rectangle rect = new Rectangle(0, 0, this.Width, this.Height);
            int radius = 50;
            System.Drawing.Drawing2D.GraphicsPath roundRect = new System.Drawing.Drawing2D.GraphicsPath();
            //顶端 
            roundRect.AddLine(rect.Left + radius - 1, rect.Top - 1, rect.Right - radius, rect.Top - 1);
            //右上角 
            roundRect.AddArc(rect.Right - radius, rect.Top - 1, radius, radius, 270, 90);
            //右边 
            roundRect.AddLine(rect.Right, rect.Top + radius, rect.Right, rect.Bottom - radius);
            //右下角
            roundRect.AddArc(rect.Right - radius, rect.Bottom - radius, radius, radius, 0, 90);
            //底边 
            roundRect.AddLine(rect.Right - radius, rect.Bottom, rect.Left + radius, rect.Bottom);
            //左下角 
            roundRect.AddArc(rect.Left - 1, rect.Bottom - radius, radius, radius, 90, 90);
            //左边 
            roundRect.AddLine(rect.Left - 1, rect.Top + radius, rect.Left - 1, rect.Bottom - radius);
            //左上角 
            roundRect.AddArc(rect.Left - 1, rect.Top - 1, radius, radius, 180, 90);

            this.Region = new Region(roundRect);

            base.OnPaint(pe);
        }
    }
}
